package com.example.d8_homework.homework05;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Test {

    // 定义首次休息日为2020年2月1日
    public static final LocalDate FIRST_REST_DAY = LocalDate.of(2020, 2, 1);

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入查询月份（格式：YYYY-MM）:");
        // 用户输入的日期
        String input = sc.nextLine();
        // 获取年份和月份
        int year = Integer.parseInt(input.substring(0, 4));
        int month = Integer.parseInt(input.substring(5, 7));

        // 1.计算该月最大天数
        LocalDate startDate = LocalDate.of(year, month, 1); // 设置起始日期为当月的第一天
        LocalDate endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); // 获取该月份的最后一天
        int maxDay = endDate.getDayOfMonth(); // 获取该月份的最大天数
        System.out.println(maxDay);

        // 2.计算首次休息日到输入月份的间隔天数
        long intervalDays = ChronoUnit.DAYS.between(FIRST_REST_DAY, endDate); // 使用ChronoUnit计算两个日期之间的天数差

        // 3.计算隔天数中的所有休息日,并把他们存入到集合中
        List<LocalDate> allRestDays = findRestDays(intervalDays);

        // 找出输入月份中下休息日
        List<LocalDate> restDaysInMonth = findRestDaysInMonth(allRestDays, startDate, endDate);

        // 统计输入月份的休息天数
        int totalRestDays = restDaysInMonth.size();

        // 统计输入月份中周末休息的天数
        int totalWeekendRestDays = countWeekendRestDays(restDaysInMonth);

        // 输出结果
        System.out.println(year + "-" + month + "的最大天数: " + maxDay);
        System.out.println("间隔天数: " + intervalDays);
        System.out.println("间隔天数中,所有的休息日: " + allRestDays);
        System.out.println("输入月份的休息日: " + restDaysInMonth);
        System.out.println("输入月份的休息天数: " + totalRestDays);
        System.out.println("间隔天数中,休息日是周末,使用[]标注: " + formatWeekendRestDays(allRestDays));
        System.out.println("--------------------------------------------------");
        printCalendarWithRestDays(year, month, restDaysInMonth); // 打印带休息日标记的日历
    }

    /**
     * 打印带休息标记的日历
     *
     * @param year     年份
     * @param month    月份
     * @param restDays 输入月份中的所有休息日的日期集合
     */
    private static void printCalendarWithRestDays(int year, int month, List<LocalDate> restDays) {
        LocalDate date = LocalDate.of(year, month, 1); // 初始化当月第一天
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E"); // 定义星期格式

        // 打印表头
        System.out.println("日历: \t" + date.getYear() + "年\t" + date.getMonthValue() + "月\t");
        System.out.println("日\t 一\t 二\t 三\t 四\t 五\t 六\t");

        // 找到该月第一天是星期几
        int firstDayOfWeek = date.getDayOfWeek().getValue(); // 从1（周一）到7（周日）
        int maxDay = date.lengthOfMonth(); // 获取该月份的最大天数

        // 打印空白以对齐星期
        for (int i = 1; i < firstDayOfWeek; i++) {
            System.out.print("   ");
        }

        // 遍历整个月份的每一天
        for (int day = 1; day <= maxDay; day++) {
            LocalDate currentDate = LocalDate.of(year, month, day); // 当前日期
            String dayStr = String.format("%2d", day); // 格式化日期为两位数字

            // 如果当天是休息日,用中括号标记
            if (restDays.contains(currentDate)) {
                dayStr = "[" + dayStr + "]";
            }

            // 打印日期并确保对齐,每行7天
            System.out.print(dayStr + (currentDate.getDayOfWeek().getValue() % 7 == 0 ? "\n" : " "));
        }

        // 如果最后一行没有满,打印换行符
        if (date.plusDays(maxDay - 1).getDayOfWeek().getValue() != 7) {
            System.out.println();
        }
    }

    /**
     * 格式化输出周末休息日
     *
     * @param restDays 所有休息日的日期集合
     * @return 格式化后的字符串
     */
    private static String formatWeekendRestDays(List<LocalDate> restDays) {
//        StringBuilder sb = new StringBuilder();
//        for (LocalDate day : restDays) {
//            if (day.getDayOfWeek() == DayOfWeek.SATURDAY || day.getDayOfWeek() == DayOfWeek.SUNDAY) {
//                sb.append("[").append(day).append("] "); // 用中括号标记周末休息日
//            } else {
//                sb.append(day).append(" ");
//            }
//        }
//        return sb.toString().trim(); // 返回格式化后的字符串并去除末尾空格

        return restDays.stream()
                .map(day -> day.getDayOfWeek() == DayOfWeek.SATURDAY || day.getDayOfWeek() == DayOfWeek.SUNDAY
                        ? "[" + day + "]"
                        : day.toString())
                .collect(Collectors.joining(" "));
    }

    /**
     * 统计输入月份中周末休息的天数
     *
     * @param restDays 所有休息日的日期集合
     * @return 周末的天数
     */
    private static int countWeekendRestDays(List<LocalDate> restDays) {
        return (int) restDays.stream()
                .filter(day -> day.getDayOfWeek() == DayOfWeek.SATURDAY || day.getDayOfWeek() == DayOfWeek.SUNDAY)
                .count();
    }

    /**
     * 找出输入月份中的所有休息日
     *
     * @param allRestDays 所有休息日的日期集合
     * @param startDate   起始日期
     * @param endDate     结束时间
     * @return 输入月份中的所有休息日的集合
     */
    public static List<LocalDate> findRestDaysInMonth(List<LocalDate> allRestDays, LocalDate startDate, LocalDate endDate) {
        /*// 初始化用于存储输入月份休息日的集合
        List<LocalDate> restDaysInMonth = new ArrayList<>();
        // 遍历所有的休息日
        for (LocalDate restDay : allRestDays) {
            // 判断当前休息日是否在指定的月份范围内
            if (restDay.isAfter(startDate.minusDays(1)) && restDay.isBefore(endDate.plusDays(1))) {
                // 如果在范围内,则添加到结果列表中
                restDaysInMonth.add(restDay);
            }
        }
        // 返回输入月份中的所有休息日
        return restDaysInMonth;*/

        return allRestDays.stream()
                .filter(restDay -> restDay.isAfter(startDate.minusDays(1)) && restDay.isBefore(endDate.plusDays(1)))
                .collect(Collectors.toList());
    }


    /**
     * 计算从首次休息日开始所有的休息日
     *
     * @param intervalDays 间隔天数
     * @return 所有休息日的日期
     */
    private static List<LocalDate> findRestDays(long intervalDays) {
        // 存储所有休息日的集合
        List<LocalDate> restDays = new ArrayList<>();
        LocalDate currentRestDay = FIRST_REST_DAY; // 从首次休息日开始
        for (long i = 0; i < intervalDays; i += 4) { // 每四天是一个循环,即上三天班,休息一天
            restDays.add(currentRestDay); // 将当前休息日添加到集合中
            currentRestDay = currentRestDay.plusDays(4); // 下一个休息日在四天后
        }
        return restDays;
    }
}
